package com.share.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.share.device.domain.Cabinet;
import com.share.device.domain.Station;
import com.share.device.domain.StationLocation;
import com.share.device.domain.StationVo;
import com.share.device.service.ICabinetService;
import com.share.device.service.IDeviceService;
import com.share.device.service.IStationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class DeviceServiceImpl implements IDeviceService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IStationService stationService;

    @Autowired
    private ICabinetService cabinetService;

    @Override
    public List<StationVo> nearbyStation(String longitude, String latitude, Integer radius) {
        // 1.以坐标确定中心点
        GeoJsonPoint geoJsonPoint = new GeoJsonPoint(Double.parseDouble(longitude), Double.parseDouble(latitude));
        // 2.画一个50Km圆圈范围内的所有站点Location
        // 半径
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        // 创建创建圆形查询区域
        Circle circle = new Circle(geoJsonPoint, distance);
        //构建一个MongoDB查询对象  Criteria.where("location") 指定查询条件基于 location 字段
        // withinSphere(circle)表示查找在指定球面圆形区域内的文档
        Query query = Query.query(Criteria.where("location").withinSphere(circle));
        List<StationLocation> stationLocations = this.mongoTemplate.find(query, StationLocation.class);
        if (CollectionUtils.isEmpty(stationLocations)) return null;
        // 3.以位置找站点列表
        // 取得站点id list
        List<Long> stationIds = stationLocations.stream().map(StationLocation::getStationId).collect(Collectors.toList());
        List<Station> stations = stationService.list(new LambdaQueryWrapper<Station>().in(Station::getId, stationIds).isNotNull(Station::getCabinetId));

        // 4.获取柜机id列表 并组织id->info map
        List<Long> cabinetIds = stations.stream().map(item -> item.getCabinetId()).collect(Collectors.toList());
        Map<Long, Cabinet> cabinetIdInfoMap = cabinetService.list(new LambdaQueryWrapper<Cabinet>().in(Cabinet::getId, cabinetIds)).stream().
                collect(Collectors.toMap(Cabinet::getId, Cabinet -> Cabinet));

        // 5.组合sationVo 设置是否可借用 是否可归还状态
        List<StationVo> stationVos = new ArrayList<>();
        stations.forEach(item -> {
            StationVo stationVo = new StationVo();
            BeanUtils.copyProperties(item, stationVo);

            // 获取柜机信息
            Cabinet cabinet = cabinetIdInfoMap.get(item.getCabinetId());
            //可用充电宝数量大于0，可借用
            if (cabinet.getAvailableNum() > 0) {
                stationVo.setIsUsable("1");
            } else {
                stationVo.setIsUsable("0");
            }
            // 获取空闲插槽数量大于0，可归还
            if (cabinet.getFreeSlots() > 0) {
                stationVo.setIsReturn("1");
            } else {
                stationVo.setIsReturn("0");
            }

            stationVos.add(stationVo);
        });
        return stationVos;
    }
}
